package com.honey.compilation.xml;

import java.util.ArrayList;
import java.util.List;

import com.honey.core.builder.CharacterBuilder;
import com.honey.core.builder.CharacterBuilderFactory;
import com.honey.core.compiler.Compilation;
import com.honey.core.compiler.CompilationException;
import com.honey.core.compiler.IndentSpace;
import com.honey.core.types.FullyQualifiedJavaType;
import com.honey.core.utils.StringUtility;

/**
 * xml文件编译器
 * @author Administrator
 *
 */
public class XmlCompilation implements Compilation {
	
	/** xml的publicId */
	private String publicId;

	/** xml的systemId */
	private String systemId;

	/** xml文件根节点 */
	private XmlElement rootElement;

	/** xml文件注释 */
	private List<String> fileComments;

	/** 文件尾部注释 */
	private List<String> afterBodyComments;
	
	/** xml 文件版本*/
	private String version="1.0";
	
	/** xml字符编码 */
	private String encoding="UTF-8";
	
	private String standalone;
	
	/** 包路径和名称 */
	private FullyQualifiedJavaType type= null;
	
	/**
	 * 构造函数
	 * @param rootElement xml根节点
	 */
	public XmlCompilation(FullyQualifiedJavaType type, String rootElement) {
		this(type);
		setRootElement(new XmlElement(rootElement));
	}
	
	/**
	 * 构造函数
	 * @param rootElement xml根节点
	 */
	public XmlCompilation(FullyQualifiedJavaType type, XmlElement rootElement) {
		this(type);
		setRootElement(rootElement);
	}
	
	/**
	 * 构造函数. 如果publicId和systemId同时为null表示不添加DOCTYPE
	 * @param publicId xml文件的publicId 
	 * @param systemId xml文件的systemId
	 */
	public XmlCompilation(FullyQualifiedJavaType type, String publicId, String systemId) {
		this(type);
		setPublicId(publicId);
		setSystemId(systemId);
	}

	/**
	 * 构造函数
	 */
	public XmlCompilation(FullyQualifiedJavaType type) {
		fileComments = new ArrayList<String>();
		afterBodyComments = new ArrayList<String>();
		this.type = type;
	}

	/**
	 * 获取xml的根节点
	 * @return
	 */
	public XmlElement getRootElement() {
		return rootElement;
	}

	/**
	 * 设定xml根节点
	 * @param rootElement
	 */
	public void setRootElement(XmlElement rootElement) {
		this.rootElement = rootElement;
	}

	/**
	 * 获取xml的publicid.如果publicId和systemId同时不为null表示不添加DOCTYPE
	 * @return
	 */
	public String getPublicId() {
		return publicId;
	}

	/**
	 * 设定xml的publicid,如果publicId和systemId同时不为null表示不添加DOCTYPE
	 * @param publicId
	 */
	public void setPublicId(String publicId) {
		this.publicId = publicId;
	}

	/**
	 * 获取xml的systemid,如果publicId和systemId同时不为null表示不添加DOCTYPE
	 * @return
	 */
	public String getSystemId() {
		return systemId;
	}
	
	
	/**
	 * 设定xml的Systemid,如果publicId和systemId同时不为null表示不添加DOCTYPE
	 * @param systemId
	 */
	public void setSystemId(String systemId) {
		this.systemId = systemId;
	}

	/**
	 * 获取xml文件版本
	 * @return
	 */
	public String getVersion() {
		return version;
	}

	/**
	 * 设定xml文件版本
	 * @param version
	 */
	public void setVersion(String version) {
		if(StringUtility.stringHasValue(version))
			this.version = version;
		else
			this.version="1.0";
	}

	
	public String getStandalone() {
		return standalone;
	}

	public void setStandalone(String standalone) {
		this.standalone = standalone;
	}

	/**
	 * 获取xml文件的字符集编码
	 * @return
	 */
	public String getEncoding() {
		return encoding;
	}

	/**
	 * 设定xml文件的字符集编码
	 * @param encoding
	 */
	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.honey.core.compiler.Compilation#addFileComment(java.lang.String[])
	 */
	@Override
	public void addFileComment(String... comments) {
		for (String comment : comments) {
			if (comment != null)
				this.fileComments.add(comment);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see com.honey.core.compiler.Compilation#addAfterBodyComment(java.lang.String[])
	 */
	@Override
	public void addAfterBodyComment(String... comments) {
		for (String comment : comments) {
			if (comment != null)
				this.afterBodyComments.add(comment);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.honey.core.compiler.Compilation#getFileComments()
	 */
	@Override
	public List<String> getFileComments() throws CompilationException {

		return this.fileComments;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.honey.core.compiler.Compilation#getType()
	 */
	@Override
	public FullyQualifiedJavaType getType() {
		return type;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.honey.core.compiler.Compilation#compiledContent()
	 */
	@Override
	public CharacterBuilder compiledContent() {
		CharacterBuilder answer = CharacterBuilderFactory.createC16StringBuilder();
		//String standalone = StringUtility.stringHasValue(this.standalone)?"standalone=\"yes\""
		answer.append("<?xml version=\""+getVersion()+"\" encoding=\""+getEncoding()+"\" ?>"); 
		if (publicId != null || systemId != null) {
			boolean isPublicId =StringUtility.stringHasValue(publicId);
			boolean isSystemId =StringUtility.stringHasValue(systemId);
			IndentSpace.newLine(answer);
			answer.append("<!DOCTYPE ")
			.append(rootElement.getName());
			if( isPublicId ){
				answer.append(" PUBLIC \"")
				.append(publicId).append("\"");
				if(isSystemId){
					answer.append(" \"")
					.append(systemId)
					.append("\"");
				}
			}else if(! isPublicId && isSystemId){
				answer.append(" SYSTEM \"")
				.append(systemId)
				.append("\"");
			}
			answer.append(">"); 
		}
		if (fileComments.size() > 0) {
			IndentSpace.newLine(answer);
			answer.append("<!--"); 
			for (String comment : fileComments) {
				IndentSpace.newSpace(answer, 1);
				answer.append(comment); 
			}
			IndentSpace.newLine(answer);
			answer.append("-->"); 
		}
		IndentSpace.newLine(answer);
		answer.append(rootElement.compiledContent(0));

		IndentSpace.newLine(answer);
		if (afterBodyComments.size() > 0) {
			for (String comment : afterBodyComments) {
				IndentSpace.newLine(answer);
				answer.append("<!-- ").append(comment).append(" -->");
			}
		}
		return answer;
	}
}
